package com.freak.freakmusic.app

import android.annotation.TargetApi
import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.ActivityInfo
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Point
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import androidx.multidex.MultiDex
import androidx.multidex.MultiDexApplication
import com.freak.freakmusic.R
import com.freak.freakmusic.base.IActivityStatusBar
import com.freak.freakmusic.constants.Constants
import com.freak.freakmusic.net.factory.CustomConverterFactory
import com.freak.freakmusic.net.status.NetStateChangeReceiver
import com.freak.freakmusic.receiver.HeadsetReceiver
import com.freak.freakmusic.receiver.MyPlayerReceiver
import com.freak.kotlinhttpmanager.kotlinhttpmanager.HttpMethods
import com.freak.kotlinhttpmanager.kotlinhttpmanager.log.LogLevel
import com.freak.kotlinhttpmanager.kotlinhttpmanager.log.LogUtil
import com.ximalaya.ting.android.opensdk.auth.constants.XmlyConstants
import com.ximalaya.ting.android.opensdk.constants.ConstantsOpenSdk
import com.ximalaya.ting.android.opensdk.constants.DTransferConstants
import com.ximalaya.ting.android.opensdk.datatrasfer.AccessTokenManager
import com.ximalaya.ting.android.opensdk.datatrasfer.CommonRequest
import com.ximalaya.ting.android.opensdk.httputil.XimalayaException
import com.ximalaya.ting.android.opensdk.player.appnotification.XmNotificationCreater
import com.ximalaya.ting.android.opensdk.util.BaseUtil
import com.ximalaya.ting.android.opensdk.util.Logger
import com.ximalaya.ting.android.player.XMediaPlayerConstants
import com.ximalaya.ting.android.sdkdownloader.XmDownloadManager
import com.ximalaya.ting.android.sdkdownloader.http.RequestParams
import com.ximalaya.ting.android.sdkdownloader.http.app.RequestTracker
import com.ximalaya.ting.android.sdkdownloader.http.request.UriRequest
import okhttp3.*
import org.json.JSONException
import org.json.JSONObject
import org.xutils.x
import java.io.IOException
import java.util.*


/**
 * @author Freak
 * @date 2019/9/11.
 */


class App : MultiDexApplication() {
    val REFRESH_TOKEN_URL = "https://api.ximalaya.com/oauth2/refresh_token?"
    val REDIRECT_URL = if (DTransferConstants.isRelease)
        "http://api.ximalaya.com/openapi-collector-app/get_access_token"
    else
        "http://qf.test.ximalaya.com/access_token/callback"
    /**
     * 存放activity的列表
     */
    private var allActivities: HashMap<Class<*>, Activity>? = null


    /**
     * 获取状态栏高度
     *
     * @return
     */
    private val statusBarHeight: Int
        get() {
            var statusBarHeight = 0
            val resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android")
            if (resourceId > 0) {
                statusBarHeight = getResources().getDimensionPixelSize(resourceId)
            }
            return statusBarHeight
        }

    override fun onCreate() {
        super.onCreate()
        instance = this
        initReceiver()
        initXMLY()
        LogUtil.init("FreakMusic", true)
        HttpMethods
            .instanceBuilder
            .setBaseUrl(Constants.getBaseUrl(Constants.SERVER_TYPE))//设置域名
            .setLogLevel(LogLevel.ERROR)//设置日志打印级别，使用默认的日志打印才需要设置这个
            .setLogName("FreakMusic")//设置默认日志打印名字
            .setIsOpenLog(true)//设置是否开启框架默认的日志打印
            .setUseDefaultSSLSocketFactory(true)
            //                .setCookieJar(new CookieJarImpl())//设置自定义的cookiejar
            //                .setLogger(new HttpLogger())//设置自定义logger，此设置是打印网络请求的数据（如果设置了自定义的，则框架默认的则不需要设置）
            //                .setLevel(LoggerLevel.BODY)//设置日志打印级别（自定义logger可设置，框架默认的是BODY级别，如果上架需要关闭日志打印，则设置setIsOpenLog(false)即可）
            .setReadTimeOut(60)
            .setConnectTimeOut(60)
            .setWriteTimeOut(60)
            //                .setInterceptor(new CommonParametersInterceptor())//设置拦截器
            //                .setNetworkInterceptor(new CommonParametersInterceptor())//设置拦截器
            .setFactory(CustomConverterFactory.create())//设置自定义解析器
        //                .setInterceptors(new CommonParametersInterceptor());//设置多个拦截器
        registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                //限制竖屏
                //8.0.0版本系统，同时设置竖屏和设置全屏透明冲突，
                activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
                resetDensity(applicationContext, DESIGN_WIDTH.toFloat())
                resetDensity(activity, DESIGN_WIDTH.toFloat())
                setImmersiveStatusBar(activity)

            }

            override fun onActivityStarted(activity: Activity) {
                setToolBar(activity)
                resetDensity(applicationContext, DESIGN_WIDTH.toFloat())
                resetDensity(activity, DESIGN_WIDTH.toFloat())
            }

            override fun onActivityResumed(activity: Activity) {
                resetDensity(applicationContext, DESIGN_WIDTH.toFloat())
                resetDensity(activity, DESIGN_WIDTH.toFloat())
            }

            override fun onActivityPaused(activity: Activity) {

            }

            override fun onActivityStopped(activity: Activity) {

            }

            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
                resetDensity(applicationContext, DESIGN_WIDTH.toFloat())
                resetDensity(activity, DESIGN_WIDTH.toFloat())
            }

            override fun onActivityDestroyed(activity: Activity) {}
        })


    }

    /************ 配置喜马拉雅 **************/
    private fun initXMLY() {
        x.Ext.init(this)

        ConstantsOpenSdk.isDebug = true
        XMediaPlayerConstants.isDebug = true
        if (BaseUtil.isMainProcess(this)) {
            val mp3 = getExternalFilesDir("mp3")!!.absolutePath
            println("地址是  $mp3")
            val mXimalaya = CommonRequest.getInstanse()
            if (DTransferConstants.isRelease) {
                val mAppSecret = "0aeaa9c4ad6c33de3a94bc3c83cf7fc7"
                mXimalaya.setAppkey("f829f4e0a7245290966f235e8fb5276f")
                mXimalaya.setPackid("com.freak.freakmusic")
                mXimalaya.init(this, mAppSecret)
            } else {
                val mAppSecret = "0aeaa9c4ad6c33de3a94bc3c83cf7fc7"
                mXimalaya.setAppkey("f829f4e0a7245290966f235e8fb5276f")
                mXimalaya.setPackid("com.freak.freakmusic")
                mXimalaya.init(this, mAppSecret)
            }

            AccessTokenManager.getInstanse().init(this)
            if (AccessTokenManager.getInstanse().hasLogin()) {
                registerLoginTokenChangeListener(this)
            }

            // 下载sdk
            XmDownloadManager.Builder(this)
                .maxDownloadThread(3)            // 最大的下载个数 默认为1 最大为3
                .maxSpaceSize(java.lang.Long.MAX_VALUE)    // 设置下载文件占用磁盘空间最大值，单位字节。不设置没有限制
                .connectionTimeOut(15000)        // 下载时连接超时的时间 ,单位毫秒 默认 30000
                .readTimeOut(15000)                // 下载时读取的超时时间 ,单位毫秒 默认 30000
                .fifo(false)                    // 等待队列的是否优先执行先加入的任务. false表示后添加的先执行(不会改变当前正在下载的音频的状态) 默认为true
                .maxRetryCount(3)                // 出错时重试的次数 默认2次
                .progressCallBackMaxTimeSpan(1000)//  进度条progress 更新的频率 默认是800
                .requestTracker(requestTracker)    // 日志 可以打印下载信息
                .savePath(mp3)    // 保存的地址 会检查这个地址是否有效
                .create()
        }

        if (BaseUtil.isPlayerProcess(this)) {
            val instanse = XmNotificationCreater.getInstanse(this)
            instanse.setNextPendingIntent(null as PendingIntent?)
            instanse.setPrePendingIntent(null as PendingIntent?)

            val actionName = "com.app.test.android.Action_Close"
            val intent = Intent(actionName)
            intent.setClass(this, MyPlayerReceiver::class.java!!)
            val broadcast = PendingIntent.getBroadcast(this, 0, intent, 0)
            instanse.setClosePendingIntent(broadcast)

            val pauseActionName = "com.app.test.android.Action_PAUSE_START"
            val intent1 = Intent(pauseActionName)
            intent1.setClass(this, MyPlayerReceiver::class.java!!)
            val broadcast1 = PendingIntent.getBroadcast(this, 0, intent1, 0)
            instanse.setStartOrPausePendingIntent(broadcast1)
        }
    }

    fun unregisterLoginTokenChangeListener() {
        CommonRequest.getInstanse().iTokenStateChange = null
    }

    fun registerLoginTokenChangeListener(context: Context) {
        // 使用此回调了就表示贵方接了需要用户登录才能访问的接口,如果没有此类接口可以不用设置此接口,之前的逻辑没有发生改变
        CommonRequest.getInstanse().iTokenStateChange = object : CommonRequest.ITokenStateChange {
            // 此接口表示token已经失效 ,
            override fun getTokenByRefreshSync(): Boolean {

                if (!TextUtils.isEmpty(AccessTokenManager.getInstanse().refreshToken)) {
                    try {
                        return refreshSync()
                    } catch (e: XimalayaException) {
                        e.printStackTrace()
                    }

                }
                return false
            }

            override fun getTokenByRefreshAsync(): Boolean {
                LogUtil.e("getTokenByRefreshAsync")
                if (!TextUtils.isEmpty(AccessTokenManager.getInstanse().refreshToken)) {
                    try {
                        refresh()
                        return true
                    } catch (e: XimalayaException) {
                        e.printStackTrace()
                    }

                }
                return false
            }

            override fun tokenLosted() {
                LogUtil.e("tokenLosted")
//                val intent = Intent(context, XMAuthDemoActivity::class.java)
//                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
//                context.startActivity(intent)
            }
        }
    }


    @Throws(XimalayaException::class)
    fun refresh() {
        val client = OkHttpClient().newBuilder()
            .followRedirects(false)
            .build()
        val builder = FormBody.Builder()
        builder.add(XmlyConstants.AUTH_PARAMS_GRANT_TYPE, "refresh_token")
        builder.add(
            XmlyConstants.AUTH_PARAMS_REFRESH_TOKEN,
            AccessTokenManager.getInstanse().tokenModel.refreshToken
        )
        builder.add(XmlyConstants.AUTH_PARAMS_CLIENT_ID, CommonRequest.getInstanse().appKey)
        builder.add(XmlyConstants.AUTH_PARAMS_DEVICE_ID, CommonRequest.getInstanse().deviceId)
        builder.add(XmlyConstants.AUTH_PARAMS_CLIENT_OS_TYPE, XmlyConstants.ClientOSType.ANDROID)
        builder.add(XmlyConstants.AUTH_PARAMS_PACKAGE_ID, CommonRequest.getInstanse().packId)
        builder.add(XmlyConstants.AUTH_PARAMS_UID, AccessTokenManager.getInstanse().uid)
        builder.add(XmlyConstants.AUTH_PARAMS_REDIRECT_URL, REDIRECT_URL)
        val body = builder.build()

        val request = Request.Builder()
            .url("https://api.ximalaya.com/oauth2/refresh_token?")
            .post(body)
            .build()
        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                Logger.d("refresh", "refreshToken, request failed, error message = " + e.message)
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                val statusCode = response.code()
                val body = response.body()!!.string()

                println("TingApplication.refreshSync  1  $body")

                var jsonObject: JSONObject? = null
                try {
                    jsonObject = JSONObject(body)
                } catch (e: JSONException) {
                    e.printStackTrace()
                }

                if (jsonObject != null) {
                    AccessTokenManager.getInstanse().setAccessTokenAndUid(
                        jsonObject.optString("access_token"),
                        jsonObject.optString("refresh_token"),
                        jsonObject.optLong("expires_in"),
                        jsonObject
                            .optString("uid")
                    )
                }
            }
        })
    }

    @Throws(XimalayaException::class)
    fun refreshSync(): Boolean {
        val client = OkHttpClient().newBuilder()
            .followRedirects(false)
            .build()
        val builder = FormBody.Builder()
        builder.add(XmlyConstants.AUTH_PARAMS_GRANT_TYPE, "refresh_token")
        builder.add(
            XmlyConstants.AUTH_PARAMS_REFRESH_TOKEN,
            AccessTokenManager.getInstanse().tokenModel.refreshToken
        )
        builder.add(XmlyConstants.AUTH_PARAMS_CLIENT_ID, CommonRequest.getInstanse().appKey)
        builder.add(XmlyConstants.AUTH_PARAMS_DEVICE_ID, CommonRequest.getInstanse().deviceId)
        builder.add(XmlyConstants.AUTH_PARAMS_CLIENT_OS_TYPE, XmlyConstants.ClientOSType.ANDROID)
        builder.add(XmlyConstants.AUTH_PARAMS_PACKAGE_ID, CommonRequest.getInstanse().packId)
        builder.add(XmlyConstants.AUTH_PARAMS_UID, AccessTokenManager.getInstanse().uid)
        builder.add(XmlyConstants.AUTH_PARAMS_REDIRECT_URL, REDIRECT_URL)
        val body = builder.build()

        val request = Request.Builder()
            .url(REFRESH_TOKEN_URL)
            .post(body)
            .build()
        try {
            val execute = client.newCall(request).execute()
            if (execute.isSuccessful) {
                try {
                    val string = execute.body()!!.string()
                    val jsonObject = JSONObject(string)
                    LogUtil.json(jsonObject.toString())
                    println("TingApplication.refreshSync  2  $string")

                    AccessTokenManager.getInstanse().setAccessTokenAndUid(
                        jsonObject.optString("access_token"),
                        jsonObject.optString("refresh_token"),
                        jsonObject.optLong("expires_in"),
                        jsonObject
                            .optString("uid")
                    )
                } catch (e: JSONException) {
                    e.printStackTrace()
                }

                return true
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return false
    }


    private val requestTracker = object : RequestTracker {
        override fun onWaiting(params: RequestParams) {
            LogUtil.e("TingApplication : onWaiting $params")
        }

        override fun onStart(params: RequestParams) {
            LogUtil.e("TingApplication : onStart $params")
        }

        override fun onRequestCreated(request: UriRequest) {
            LogUtil.e("TingApplication : onRequestCreated $request")
        }

        override fun onSuccess(request: UriRequest, result: Any) {
            LogUtil.e("TingApplication : onSuccess $request   result = $result")
        }

        override fun onRemoved(request: UriRequest) {
            LogUtil.e("TingApplication : onRemoved $request")
        }

        override fun onCancelled(request: UriRequest) {
            LogUtil.e("TingApplication : onCanclelled $request")
        }

        override fun onError(request: UriRequest, ex: Throwable, isCallbackError: Boolean) {
            LogUtil.e("TingApplication : onError $request   ex = $ex   isCallbackError = $isCallbackError")
        }

        override fun onFinished(request: UriRequest) {
            LogUtil.e("TingApplication : onFinished $request")
        }
    }

    /************ 配置喜马拉雅 **************/
    private fun initReceiver() {
        //耳机拔插广播
        val headsetReceiver = HeadsetReceiver()
        val headsetFilter = IntentFilter(Intent.ACTION_HEADSET_PLUG)
        registerReceiver(headsetReceiver, headsetFilter)
        //网络变化广播
        NetStateChangeReceiver.registerReceiver(this)
    }

    protected override fun attachBaseContext(base: Context) {
        super.attachBaseContext(base)
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base)
    }

    /**
     * 设置ToolBar
     *
     * @param activity
     */
    private fun setToolBar(activity: Activity) {
        if (activity.findViewById<Toolbar>(R.id.tool_bar) != null && (activity as AppCompatActivity).supportActionBar == null) {
            val toolbar = activity.findViewById<Toolbar>(R.id.tool_bar)
            if (!TextUtils.isEmpty(activity.getTitle())) {
                toolbar.setTitle(activity.getTitle())
            } else {
                toolbar.setTitle("")
            }

            if ((activity as IActivityStatusBar).statusBarColor !== 0) {
                toolbar.setBackgroundColor((activity as IActivityStatusBar).statusBarColor)
            } else {
                toolbar.setBackgroundColor(
                    ContextCompat.getColor(
                        applicationContext,
                        R.color.color_white
                    )
                )
            }

            activity.setSupportActionBar(toolbar)
            val actionBar = activity.supportActionBar
            if (actionBar != null) {
                actionBar.setHomeButtonEnabled(true)
                actionBar.setDisplayHomeAsUpEnabled(true)
            }
            toolbar.setNavigationOnClickListener(View.OnClickListener { activity.onBackPressed() })
        }
    }


    /**
     * 判断是否是亮色
     *
     * @param color
     * @return
     */
    private fun isLightColor(@ColorInt color: Int): Boolean {
        return ColorUtils.calculateLuminance(color) >= 0.5
    }

    /**
     * 设置状态栏
     *
     * @param activity
     */
    private fun setImmersiveStatusBar(activity: Activity) {
            if (activity is IActivityStatusBar) {
                if ((activity as IActivityStatusBar).statusBarColor !== 0) {
                    setTranslucentStatus(activity)
                    addImmersiveStatusBar(
                        activity,
                        (activity as IActivityStatusBar).statusBarColor
                    )
                } else {
                    if ((activity as IActivityStatusBar).drawableStatusBar !== 0) {
                        setTranslucentStatus(activity)
                        addImmersiveShadeStatusBar(
                            activity,
                            (activity as IActivityStatusBar).drawableStatusBar
                        )
                    }
                }
            }
    }

    /**
     * 添加自定义状态栏
     *
     * @param activity
     */
    private fun addImmersiveStatusBar(activity: Activity, color: Int) {
        val contentFrameLayout = activity.findViewById<ViewGroup>(android.R.id.content)
        val contentView = contentFrameLayout.getChildAt(0)
        if (contentView != null) {
            contentView.fitsSystemWindows = true
        }

        val statusBar = View(activity)
        val params = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        if (hasNotchInScreen(activity)) {
            params.height = getNotchSize(activity)[1]
        } else {
            params.height = statusBarHeight
        }
        params.height = statusBarHeight
        statusBar.layoutParams = params
        statusBar.setBackgroundColor(color)
        if (isLightColor(color)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                statusBar.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            } else {
                statusBar.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
            }
        } else {
            statusBar.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
        }
        contentFrameLayout.addView(statusBar)
    }

    /**
     * 设置状态栏渐变色
     *
     * @param activity activity
     * @param drawable drawable资源文件
     */
    private fun addImmersiveShadeStatusBar(activity: Activity, @DrawableRes drawable: Int) {
        val contentFrameLayout = activity.findViewById<ViewGroup>(android.R.id.content)
        val contentView = contentFrameLayout.getChildAt(0)
        if (contentView != null && Build.VERSION.SDK_INT >= 14) {
            contentView.fitsSystemWindows = true
        }

        val statusBar = View(activity)
        val params = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        if (hasNotchInScreen(activity)) {
            params.height = getNotchSize(activity)[1]
        } else {
            params.height = statusBarHeight
        }
        //        params.height = getStatusBarHeight();
        statusBar.layoutParams = params
        statusBar.setBackgroundResource(drawable)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            statusBar.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
        } else {
            statusBar.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
        }
        contentFrameLayout.addView(statusBar)
    }

    /**
     * 设置状态栏为透明
     *
     * @param activity
     */
    private fun setTranslucentStatus(activity: Activity) {
        //******** 5.0以上系统状态栏透明 ********

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val window = activity.window
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            window.decorView.systemUiVisibility =
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        }
    }

    /**
     * 添加activity
     *
     * @param activity
     * @param tClass
     */
    fun addActivity(activity: AppCompatActivity, tClass: Class<*>) {
        if (allActivities == null) {
            allActivities = LinkedHashMap()
        }

        //        LogUtil.e("activity堆栈 addActivity " + activity.getClass().getSimpleName());
        allActivities!![tClass] = activity
        //        LogUtil.d("activity堆栈 addActivity  " + allActivities);
    }

    /**
     * 移除activity,代替finish
     *
     * @param activity
     */
    fun removeActivity(activity: AppCompatActivity) {
        if (allActivities != null) {
            //            LogUtil.d("activity堆栈 removeActivity  " + allActivities);
            //            LogUtil.d("activity堆栈 removeActivity  " + activity.getClass().getSimpleName());
            if (allActivities!!.containsValue(activity)) {
                allActivities!!.remove(activity.javaClass)
                //                LogUtil.e("activity堆栈 removeActivity " + activity.getClass().getSimpleName());
            }
        }
    }

    /**
     * 移除所有activity并结束程序
     */
    fun finishActivity() {
        if (allActivities != null && allActivities!!.size > 0) {
            val sets = allActivities!!.entries
            for ((_, value) in sets) {
                if (!value.isFinishing) {
                    value.finish()
                }
            }
            allActivities!!.clear()
        }
        android.os.Process.killProcess(android.os.Process.myPid())
    }


    /**
     * 移除所有的Activity
     */
    fun removeAllActivity() {
        if (allActivities != null && allActivities!!.size > 0) {
            val sets = allActivities!!.entries
            LogUtil.d("activity堆栈  removeAllActivity  " + allActivities!!)
            for ((_, value) in sets) {
                if (!value.isFinishing) {
                    value.finish()
                }
            }
            allActivities!!.clear()
        }
    }

    /**
     * 判断一个Activity 是否存在
     *
     * @param clz
     * @return
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    fun <T : AppCompatActivity> isActivityExist(clz: Class<T>): Boolean {
        val res: Boolean
        val activity = getActivity(clz)
        res = if (activity == null) {
            false
        } else {
            !(activity.isFinishing || activity.isDestroyed)
        }

        return res
    }

    /**
     * 获得指定activity实例
     *
     * @param clazz Activity 的类对象
     * @return
     */
    fun <T : AppCompatActivity> getActivity(clazz: Class<T>): T? {
        return allActivities!![clazz] as T?
    }


    /**
     * 根据Pid获取当前进程的名字，一般就是当前app的包名
     *
     * @param pid 进程的id
     * @return 返回进程的名字
     */
    private fun getAppName(pid: Int): String? {
        var processName: String? = null
        val activityManager =
            instance!!.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val list = activityManager.runningAppProcesses
        val i = list.iterator()
        while (i.hasNext()) {
            val info = i.next() as ActivityManager.RunningAppProcessInfo
            try {
                if (info.pid == pid) {
                    // 根据进程的信息获取当前进程的名字
                    processName = info.processName
                    // 返回当前进程名
                    return processName
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }
        // 没有匹配的项，返回为null
        return processName
    }


    companion object {
        val DESIGN_WIDTH = 375.0
        @get:Synchronized
        var instance: App? = null

        /**
         * 以pt为单位重新计算大小
         */
        fun resetDensity(context: Context?, designWidth: Float) {
            if (context == null) {
                return
            }
            val size = Point()
            (context.getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(size)
            val resources = context.resources
            resources.displayMetrics.xdpi = size.x / designWidth * 72f
            val metrics = getMetricsOnMIUI(context.resources)
            if (metrics != null) {
                metrics.xdpi = size.x / designWidth * 72f
            }
        }

        /**
         * 解决MIUI屏幕适配问题
         *
         * @param resources
         * @return
         */
        private fun getMetricsOnMIUI(resources: Resources): DisplayMetrics? {
            if ("MiuiResources" == resources.javaClass.simpleName || "XResources" == resources.javaClass.simpleName) {
                try {
                    val field = Resources::class.java.getDeclaredField("mTmpMetrics")
                    field.isAccessible = true
                    return field.get(resources) as DisplayMetrics
                } catch (e: Exception) {
                    return null
                }

            }
            return null
        }


        /**
         * 判断是否是刘海屏  华为手机
         *
         * @param context
         * @return
         */
        fun hasNotchInScreen(context: Context): Boolean {

            var ret = false

            try {

                val cl = context.classLoader

                val hwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil")

                val get = hwNotchSizeUtil.getMethod("hasNotchInScreen")

                ret = get.invoke(hwNotchSizeUtil) as Boolean

            } catch (e: ClassNotFoundException) {

                Log.e("test", "hasNotchInScreen ClassNotFoundException")

            } catch (e: NoSuchMethodException) {

                Log.e("test", "hasNotchInScreen NoSuchMethodException")

            } catch (e: Exception) {

                Log.e("test", "hasNotchInScreen Exception")

            }

            LogUtil.e("是否刘海屏-->$ret")
            return ret

        }

        /**
         * 获取刘海屏尺寸 华为手机
         *
         * @param context
         * @return
         */
        fun getNotchSize(context: Context): IntArray {

            var ret = intArrayOf(0, 0)

            try {

                val cl = context.classLoader

                val hwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil")

                val get = hwNotchSizeUtil.getMethod("getNotchSize")

                ret = get.invoke(hwNotchSizeUtil) as IntArray

            } catch (e: ClassNotFoundException) {

                LogUtil.e("getNotchSize ClassNotFoundException")

            } catch (e: NoSuchMethodException) {

                LogUtil.e("getNotchSize NoSuchMethodException")

            } catch (e: Exception) {

                LogUtil.e("getNotchSize Exception")

            }

            LogUtil.e("刘海屏尺寸-->$ret")
            return ret

        }

    }

}

